/*
*
==============================================================================
*  Name        : OmenOctree.h
*  Part of     : Omen Game Engine
*  Description : OctreeNode and Octree implentation classes
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

#include <IOmenOctree.h>
#include <IOmenScene.h>

namespace Omen
{
    /// <summary>IOctreeNode represents one node in the Octree</summary>
    class OctreeNode : public Omen::IOctreeNode
    {
    #define GUID_OMEN_OCTREENODE "A2F35735-0A8E-4A68-A623-E81AAB4AFBF7"

    public:
        OMEN_API virtual Omen_GUID classId() const { return OMEN_UUID(GUID_OMEN_OCTREENODE); }   /// <summary>inherited from Omen::IObject, returns the class id of IOctreeNode implementing class</summary>

        OMEN_API OctreeNode();
        OMEN_API OctreeNode( const OctreeNode& other );
        OMEN_API virtual ~OctreeNode();

        OMEN_API virtual Omen::AABB& boundingBox();                                              /// <summary>Returns reference to bounding box of this node</summary>
        OMEN_API virtual void setBoundingBox( const Omen::AABB& boundingBox );                   /// <summary>Sets the bounding box of this node</summary>
            
        OMEN_API virtual IOctreeNode** children();                                               /// <summary>Returns pointer to the 8 child nodes</summary>
        OMEN_API virtual bool leaf() const;                                                      /// <summary>Returns true if this node is a leaf node</summary>

        OMEN_API virtual void addFace( Omen::IMesh::Face* pFace );                               /// <summary>Add face to the node</summary>
        OMEN_API virtual unsigned long faceCount();                                              /// <summary>In case this is a leaf node, return the number of faces contained in this node, otherwise 0</summary>
        OMEN_API virtual void getFaces( Omen::IMesh::Face** pListFaces, unsigned long maxSize ); /// <summary>Get the faces contained in this node</summary>

        OMEN_API virtual unsigned int depth() const;                                             /// <summary>Returns how deep in the hierarchy this node is</summary>

        /// Engine Internal functions
        void subDivide( unsigned int depth, std::vector<Omen::IMesh::Face*>& listFaces, unsigned int maximumDepth, unsigned int minimumFaceCount );

    protected:
    private:
        OctreeNode*     m_children[8];                                                  /// <summary>The eight child nodes</summary>
        bool            m_bIsLeafNode;                                                  /// <summary>Boolean true if this is a leaf node, false otherwise</summary>
        Omen::AABB      m_boundingBox;                                                  /// <summary>The bounding box of this node</summary>
        std::vector<Omen::IMesh::Face*> m_listFaces;                                    /// <summary>List of faces in this leaf node. If this is not a leaf node, the list is empty</summary>
        unsigned int    m_depth;
    };

    class Octree : public Omen::IOctree
    {
        #define GUID_OMEN_OCTREE "AD148DAD-0837-4B12-83D2-CF279E433C80"

    public:
        OMEN_API virtual Omen_GUID classId() const { return OMEN_UUID(GUID_OMEN_OCTREE); }       /// <summary>inherited from Omen::IObject, returns the class id of IOctree implementing class</summary>

        OMEN_API Octree();
        OMEN_API Octree( const Octree& other );
        OMEN_API virtual ~Octree();
        
        OMEN_API virtual IOctreeNode*    rootNode() const;
        OMEN_API virtual void setRootNode( IOctreeNode* pRootNode );

        OMEN_API virtual unsigned int maxDepth() const;                                          /// <summary>Returns the maximum depth set for this octree</summary>
        OMEN_API virtual unsigned int minimumFaceCount() const;                               /// <summary>Returns the minimum element count (object,mesh,face) that is used to stop the creation the octree in depth</summary>

    protected:
    private:
        unsigned int        m_maximumDepth;                                             /// <summary>The maximum depth of this octree</summary>
        unsigned int        m_minimumCount;                                             /// <summary>The minimum element count of items in the leaf node</summary>
        Omen::IOctreeNode*  m_pRootNode;
    };
}

OMEN_API Omen::IOctree* createOctree( const Omen::IScene* pScene, unsigned int maximumDepth, unsigned int minimumFaceCount );